package com.xdap.water.vo;

import com.xdap.water.pojo.InvestmentPhasePojo;
import com.xdap.water.pojo.ProjectItemPojo;
import com.xdap.water.pojo.ProjectReservePojo;
import lombok.Builder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;

import java.util.*;

import static java.util.stream.Collectors.groupingBy;

@Data
@Builder
@Slf4j
public class WaterCardInfoVo {
    private final String[] levels = { "province", "city", "demo", "million", "normal" };
    private List<ProjectItemPojo> projects;
    private List<InvestmentPhasePojo> phases;
    private List<ProjectReservePojo> reserves;
    public WaterCardInfoVo(List<ProjectItemPojo> projects, List<InvestmentPhasePojo> phases, List<ProjectReservePojo> reserves) {
        this.projects = projects;
        this.phases = phases;
        this.reserves = reserves;
    }

    // 计算总投资项目数量
    public int calcTotalCount() {
        return projects.size();
    }

    // 计算年度项目投资总额
    public Map<String, Object> calculate() {
        // 年度项目投资总额 年目标金额
        double totalInvestment = 0.0;
        // 省重大项目数量
        int countProvince = 0;
        // 市重大项目数
        int countCity = 0;
        // 示范项目数
        int countDemo = 0;
        // 累计完成额（万元） 已完成投资 投资进度
        double totalInvested = 0.0;
        // 投资达成率  累计 / 总投  totalInvested / totalInvestment
        double investmentRate = 0.0;
        // 省重大项目金额
        double totalProvince = 0.0;
        // 市重大项目金额
        double totalCity = 0.0;
        // 示范项目金额
        double totalDemo = 0.0;
        // 储备项目总数
        int countReserve = reserves.size();
        // 储备项目金额
        double totalReserve = 0.0;
        // 纳统金额进度
        double totalNt = 0.0;
        // 支付进度
        double totalPayment = 0.0;
        // 形象进度
        double totalImage = 0.0;
        // 完成项目个数
        int countCompleted = 0;


        // 存储最终结果的 map
        Map<String, Object> map = new HashMap<>();
        Map<String, Integer> countMap = new HashMap<>();
        Map<String, List<WaterTreeTableVo>> treeTableMap = initTreeTableMap();

        List<WaterTreeTableVo> provinceList = treeTableMap.get(levels[0]);
        List<WaterTreeTableVo> cityList = treeTableMap.get(levels[1]);
        List<WaterTreeTableVo> demoList = treeTableMap.get(levels[2]);
        List<WaterTreeTableVo> millionList = treeTableMap.get(levels[3]);
        List<WaterTreeTableVo> normalList = treeTableMap.get(levels[4]);

        ArrayList<WaterCardInfoItemVo> cardList = new ArrayList<>();

        WaterCardInfoItemVo card1 = buildWaterCardInfoItemVo(1);
        WaterCardInfoItemVo card2 = buildWaterCardInfoItemVo(2);
        WaterCardInfoItemVo card3 = buildWaterCardInfoItemVo(3);

        ArrayList<WaterCardInfoCountVo> countList1 = new ArrayList<>();
        ArrayList<WaterCardInfoCountVo> countList2 = new ArrayList<>();
        ArrayList<WaterCardInfoCountVo> countList3 = new ArrayList<>();

        ArrayList<WaterChartVo> waterChartVos = new ArrayList<>();

        for (ProjectItemPojo project : projects) {
            // 年度项目投资总额 deprecated 取值逻辑修改
            // totalInvestment += getNumber(project.getTotalCost());
            totalInvestment += getNumber(project.getYearTarget());
            // 累计额度
            totalInvested += getNumber(project.getAllDone());
            totalNt += getNumber(project.getTotalNt());
            totalPayment += getNumber(project.getPaymentAmount());
            totalImage += getNumber(project.getImageAmount());
            setMapValueCountByKey(countMap, project.getLevelOne());

            if (isYes(project.getProvinceMain())) {
                // 省重大项目
                provinceList.add(convertProjectToTreeTableVo(project));
                countProvince++;
                // deprecated 取值逻辑修改
                // totalProvince += getNumber(project.getTotalCost());
                totalProvince += getNumber(project.getYearTarget());
            }

            if (isYes(project.getCityMain())) {
                // 市重大项目
                cityList.add(convertProjectToTreeTableVo(project));
                countCity++;
                // deprecated 取值逻辑修改
                // totalCity += getNumber(project.getTotalCost());
                totalCity += getNumber(project.getYearTarget());
            }

            if (isYes(project.getDemoMain())) {
                // 示范项目
                demoList.add(convertProjectToTreeTableVo(project));
                countDemo++;
                // deprecated 取值逻辑修改
                // totalDemo += getNumber(project.getTotalCost());
                totalDemo += getNumber(project.getYearTarget());
            }

            if (isYes(project.getCompleted())) {
                countCompleted++;
            }

            if (isYes(project.getNormal())) {
                // 普通项目
                normalList.add(convertProjectToTreeTableVo(project));
            }

            if (isYes(project.getMillion())) {
                // 亿元项目
                millionList.add(convertProjectToTreeTableVo(project));
            }
        }

        for (ProjectReservePojo project : reserves) {
            totalReserve += getNumber(project.getTotalCost());
        }

        investmentRate = totalInvestment == 0.0 ? 0.0 : (totalInvested / totalInvestment) * 100.0;

        countList1.add(getCardInfoCountVo("年度总投资项目数", calcTotalCount(), null));
        countList1.add(getCardInfoCountVo("年度项目投资总额", totalInvestment, "万"));
        countList1.add(getCardInfoCountVo("省重大项目数", countProvince, null));
        countList1.add(getCardInfoCountVo("市重大项目数", countCity, null));
        countList1.add(getCardInfoCountVo("示范项目数", countDemo, null));
        card1.setInfoList(countList1);
        cardList.add(card1);

        countList2.add(getCardInfoCountVo("已完成投资", totalInvested, "万"));
        countList2.add(getCardInfoCountVo("投资达成率", investmentRate, "%"));
        countList2.add(getCardInfoCountVo("省重大项目总额", totalProvince, "万"));
        countList2.add(getCardInfoCountVo("市重大项目总额", totalCity, "万"));
        countList2.add(getCardInfoCountVo("示范项目总额", totalDemo, "万"));
        card2.setInfoList(countList2);
        cardList.add(card2);

        countList3.add(getCardInfoCountVo("储备项目总数", countReserve, null));
        countList3.add(getCardInfoCountVo("储备项目总额", totalReserve, "万"));
        // deprecated 不进行计算
        // countList3.add(getCardInfoCountVo("累计完成纳统", totalNt, "万"));
        card3.setInfoList(countList3);
        cardList.add(card3);

        // 进行水球图的逻辑
        waterChartVos.add(buildWaterChartVo("完成项目(个)", "已完成项目数", "个", countCompleted, calcTotalCount()));
        waterChartVos.add(buildWaterChartVo("投资进度(万元)", "投资进度(万)", "万", totalInvested, totalInvestment));
        waterChartVos.add(buildWaterChartVo("纳统进度(万元)", "纳统进度(万)", "万", totalNt, totalInvestment));
        waterChartVos.add(buildWaterChartVo("支付进度(万元)", "支付进度(万)", "万", totalPayment, totalInvestment));
        waterChartVos.add(buildWaterChartVo("形象进度(万元)", "形象进度(万)", "万", totalImage, totalInvestment));

        map.put("cardList", cardList);
        map.put("trapeziumList", getTrapeziumListByCountMap(countMap));
        map.put("waterChartList", waterChartVos);
        map.put("treeTableList", convertMapToTreeTable(treeTableMap));

        log.info("map => {}", map);

        return map;
    }


    private double getNumber(Double number) {
        return number == null ? 0.0 : number;
    }

    private WaterCardInfoItemVo buildWaterCardInfoItemVo(int index) {
        return WaterCardInfoItemVo.builder()
                .id(UUID.randomUUID().toString())
                .icon("custom-chart" + index)
                .build();
    }

    private boolean isYes(String yesOrNo) {
        if (StringUtils.isNotBlank(yesOrNo)) {
            return yesOrNo.equals("[\"YES\"]");
        }

        return false;
    }

    private WaterCardInfoCountVo getCardInfoCountVo(String title, Number number, String unit) {
        WaterCardInfoCountVo vo = new WaterCardInfoCountVo();

        vo.setTitle(title);
        vo.setValue(number);
        vo.setUnit(unit);

        return vo;
    }

    private void setMapValueCountByKey(Map<String, Integer> map, String key) {
        if (StringUtils.isNotBlank(key)) {
            if (map.containsKey(key)) {
                map.put(key, map.get(key) + 1);
            } else {
                map.put(key, 1);
            }
        }
    }

    private List<WaterTrapeziumItemVo> getTrapeziumListByCountMap(Map<String, Integer> map) {
        log.info("getTrapeziumListByCountMap map => {}", map);
        List<WaterTrapeziumItemVo> trapeziumItemVos = new ArrayList<>();
        for (InvestmentPhasePojo phase : phases) {
            String id = String.format("[\"%s\"]", phase.getId());
            log.info("id => {}", id);
            log.info("phase => {}", phase);
            Integer number = map.get(id);
            WaterTrapeziumItemVo vo = WaterTrapeziumItemVo.builder()
                    .id(id)
                    .label(phase.getPhaseName())
                    .number(null == number ? 0 : number)
                    .build();
            trapeziumItemVos.add(vo);
        }
        return trapeziumItemVos;
    }

    public List<WaterTrapeziumItemVo> getTrapeziumList() {
        Map<String, Integer> countMap = new HashMap<>();
        for (ProjectItemPojo project : projects) {
            setMapValueCountByKey(countMap, project.getLevelTwo());
        }

        return getTrapeziumListByCountMap(countMap);
    }

    private double calcRate(double a, double b) {
        if (b == 0.0) {
            return 0.0;
        } else {
            return Math.round((a / b) * 10000) / 10000.0;
        }
    }

    private List<WaterTreeTableVo> convertMapToTreeTable(Map<String, List<WaterTreeTableVo>> treeTableMap) {
        Map<String, Map<String, List<WaterTreeTableVo>>> map = buildTreeTableMap(treeTableMap);
        log.info("treeTableMap => {}", map);
        List<WaterTreeTableVo> treeTableList = new ArrayList<>();
        for (String levelKey : map.keySet()) {
            WaterTreeTableVo levelVo = new WaterTreeTableVo();
            levelVo.setProjectName(convertLevelToProjectName(levelKey));
            List<WaterTreeTableVo> children = new ArrayList<>();
            Map<String, List<WaterTreeTableVo>> unitMap = map.get(levelKey);
            for (String unitKey : unitMap.keySet()) {
                List<WaterTreeTableVo> tableVos = unitMap.get(unitKey);
                if (tableVos.size() > 0) {
                    WaterTreeTableVo unitVo = new WaterTreeTableVo();
                    if (StringUtils.isNotBlank(unitKey)) {
                        unitVo.setProjectName(unitKey);
                    } else {
                        unitVo.setProjectName("其他项目");
                    }
                    unitVo.setChildren(tableVos);
                    setWaterTreeTableVoOtherProperties(unitVo, tableVos);
                    children.add(unitVo);
                }
            }
            if (children.size() > 0) {
                levelVo.setChildren(children);
                setWaterTreeTableVoOtherProperties(levelVo, children);
                treeTableList.add(levelVo);
            }
        }
        return treeTableList;
    }

    private Map<String, Map<String, List<WaterTreeTableVo>>> buildTreeTableMap(Map<String, List<WaterTreeTableVo>> treeTableMap) {
        // 进行二次分组
        Map<String, Map<String, List<WaterTreeTableVo>>> map = new HashMap<>();
        for (String key : treeTableMap.keySet()) {
            List<WaterTreeTableVo> vos = treeTableMap.get(key);
            map.put(key, vos.stream().collect(groupingBy(WaterTreeTableVo::getResponsibleUnit)));
        }

        return map;
    }

    private String convertLevelToProjectName(String level) {
        if (levels[0].equals(level)) {
            return "省重大项目";
        } else if (levels[1].equals(level)) {
            return "省市重点项目";
        } else if (levels[2].equals(level)) {
            return "指挥部示范项目";
        } else if (levels[3].equals(level)) {
            return "亿元项目";
        } else if (levels[4].equals(level)) {
            return "普通项目";
        } else {
            return "其他项目";
        }
    }

    private void setWaterTreeTableVoOtherProperties(WaterTreeTableVo unitVo, List<WaterTreeTableVo> treeTableList) {
        double totalYearTargetAmount = 0.0;
        double totalInvestmentAmount = 0.0;
        double totalNtAmount = 0.0;
        double totalPaymentAmount = 0.0;
        double totalImageAmount = 0.0;

        for (WaterTreeTableVo vo : treeTableList) {
            totalYearTargetAmount += vo.getYearTargetAmount();
            totalInvestmentAmount += vo.getInvestmentAmount();
            totalNtAmount += vo.getNtAmount();
            totalPaymentAmount += vo.getPaymentAmount();
            totalImageAmount += vo.getImageAmount();
        }

        unitVo.setYearTargetAmount(totalYearTargetAmount);

        unitVo.setInvestmentAmount(totalInvestmentAmount);
        unitVo.setInvestmentRate(calcRate(totalInvestmentAmount, totalYearTargetAmount) * 100.0);

        unitVo.setNtAmount(totalNtAmount);
        unitVo.setNtRate(calcRate(totalNtAmount, totalYearTargetAmount) * 100.0);

        unitVo.setPaymentAmount(totalPaymentAmount);
        unitVo.setPaymentRate(calcRate(totalPaymentAmount, totalYearTargetAmount) * 100.0);

        unitVo.setImageAmount(totalImageAmount);
        unitVo.setImageRate(calcRate(totalImageAmount, totalYearTargetAmount) * 100.0);
    }

    private WaterTreeTableVo convertProjectToTreeTableVo(ProjectItemPojo project) {
        double yearTargetAmount = getNumber(project.getYearTarget());
        double investmentAmount = getNumber(project.getAllDone());
        double ntAmount = getNumber(project.getTotalNt());
        double paymentAmount = getNumber(project.getPaymentAmount());
        double imageAmount = getNumber(project.getImageAmount());
        WaterTreeTableVo vo = WaterTreeTableVo.builder()
                .formId(project.getFormId())
                .documentId(project.getDocumentId())
                .projectName(project.getProjectName())
                .yearTargetAmount(yearTargetAmount)
                .investmentAmount(investmentAmount)
                .investmentRate(calcRate(investmentAmount, yearTargetAmount) * 100.0)
                .ntAmount(ntAmount)
                .ntRate(calcRate(ntAmount, yearTargetAmount) * 100.0)
                .paymentAmount(paymentAmount)
                .paymentRate(calcRate(paymentAmount, yearTargetAmount) * 100.0)
                .imageAmount(imageAmount)
                .imageRate(calcRate(imageAmount, yearTargetAmount) * 100.0)
                .responsibleUnit(project.getResponsibleUnit())
                .build();
        vo.setChildren(null);
        return vo;
    }

    private WaterChartVo buildWaterChartVo(String text, String subText, String unit, Number completed, Number target) {
        WaterChartVo vo = WaterChartVo.builder()
                .text(text)
                .subText(subText)
                .number(calcRate(Double.parseDouble(completed.toString()), Double.parseDouble(target.toString())))
                .build();
        List<WaterCardInfoCountVo> countVos = new ArrayList<>();
        countVos.add(new WaterCardInfoCountVo("已完成", completed, unit));
        countVos.add(new WaterCardInfoCountVo("年目标", target, unit));
        vo.setCardInfoList(countVos);

        return vo;
    }

    private Map<String, List<WaterTreeTableVo>> initTreeTableMap() {
        Map<String, List<WaterTreeTableVo>> map = new HashMap<>();

        for (String level : levels) {
            map.put(level, new ArrayList<>());
        }
        return map;
    }
}
